package sengine;

import game.Equipment;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;

/**
 *
 * @author twoodf5611
 */
public class PlayerCharacter extends Character implements KeyListener {

    private int expLevel = 1;
    private int experience=0;
    private long lastMillis;
    private boolean spaceDown = false;
    private boolean wDown = false;
    private boolean sDown = false;
    private int lastXKey = 0;
    public static final long spriteInterval = 60;
    private Level currentStage;
    private int currentPartnerIndex = 0;
    private PartyCharacter partner;
    private ArrayList<String> partySprites = new ArrayList<>();

    public PlayerCharacter(int x, int y) {
        super(x, y, 50, 50);
        setMass(30);
        initial();
    }

    public PlayerCharacter() {
        super(0, 0, 50, 50);
        initial();
    }

    public final void initial() {
        setPhysType(Object2D.PhysicsType.MOVABLE);
        lastMillis = 0;
    }

    public void setPartner(PartyCharacter partner) {
        this.partner = partner;
    }

    public void setPartySprites(ArrayList<String> partySprites) {
        this.partySprites = partySprites;
    }

    public void leftSprite(long millis) {
        if (lastMillis <= spriteInterval) {
            setTexture(Texture.loadTexture("leftstill.png"));
        }
        if (lastMillis >= spriteInterval) {
            setTexture(Texture.loadTexture("leftmove1.png"));
        }
        if (lastMillis >= 2 * spriteInterval) {
            setTexture(Texture.loadTexture("leftmove2.png"));
        }
        if (lastMillis >= 3 * spriteInterval) {
            setTexture(Texture.loadTexture("leftmove3.png"));
        }
        if (lastMillis >= 4 * spriteInterval) {
            setTexture(Texture.loadTexture("leftstill.png"));
            lastMillis = 0;
        }
        lastMillis += millis;
    }

    public void rightSprite(long millis) {
        if (lastMillis <= spriteInterval) {
            setTexture(Texture.loadTexture("rightmove3.png"));
        }
        if (lastMillis >= spriteInterval) {
            setTexture(Texture.loadTexture("rightmove1.png"));
        }
        if (lastMillis >= 2 * spriteInterval) {
            setTexture(Texture.loadTexture("rightmove2.png"));
        }
        if (lastMillis >= 3 * spriteInterval) {
            setTexture(Texture.loadTexture("rightmove3.png"));
        }
        if (lastMillis >= 4 * spriteInterval) {
            setTexture(Texture.loadTexture("rightstill.png"));
            lastMillis = 0;
        }
        lastMillis += millis;
    }

    public void jumpSprite(long millis) {
        String jumpDir = "rightjump.png";
        if (lastXKey == Keyboard.KEY_A) {
            jumpDir = "leftjump.png";
        } else if (lastXKey == Keyboard.KEY_D) {
            jumpDir = "rightjump.png";
        }
        setTexture(Texture.loadTexture(jumpDir));
    }

    @Override
    public void update(long millis) {
        if(getX() > 4000) {
            win();
        }
        
        if(getX() > 0 && getY()>725) {
            setY(650); // To make up for our crappy collision detection
        }
        
        if (getEquipment() != null) {
            getEquipment().playerLocUpdate(getX(), getY(), getR(), getDirection());
        }

        if (Keyboard.isKeyDown(Keyboard.KEY_A)
                && Keyboard.isKeyDown(Keyboard.KEY_D)) {
            lastMillis = 0;
            stopMove();
            if (!airborne()) {
                if (lastXKey == Keyboard.KEY_D) {
                    leftSprite(millis);
                } else if (lastXKey == Keyboard.KEY_A) {
                    rightSprite(millis);
                }
            } else {
                jumpSprite(millis);
            }
        } else if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
            moveLeft();
            currentStage.centerX((int) this.getX());
            if (!airborne()) {
                leftSprite(millis);
            } else {
                jumpSprite(millis);
            }
            lastXKey = Keyboard.KEY_A;
        } else if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
            moveRight();
            currentStage.centerX((int) this.getX());
            if (!airborne()) {
                rightSprite(millis);
            } else {
                jumpSprite(millis);
            }
            lastXKey = Keyboard.KEY_D;
        } else {
            lastMillis = 0;
            stopMove();
            if (!airborne()) {
                if (lastXKey == Keyboard.KEY_A) {
                    setTexture(Texture.loadTexture("leftstill.png"));
                } else if (lastXKey == Keyboard.KEY_D) {
                    setTexture(Texture.loadTexture("rightstill.png"));
                }
            }
        }

        if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && !spaceDown && !airborne()) {
            jump();
            inAir();
            jumpSprite(millis);
            spaceDown = true;
        } else if (!Keyboard.isKeyDown(Keyboard.KEY_SPACE) && spaceDown) {
            spaceDown = false;
        }
        
        if (Keyboard.isKeyDown(Keyboard.KEY_W) && !wDown) {
            wDown = true;
            changePartyCharacter(false);
        } else if (!Keyboard.isKeyDown(Keyboard.KEY_W) && wDown) {
            wDown = false;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_S) && !sDown) {
            sDown = true;
            changePartyCharacter(true);
        } else if (!Keyboard.isKeyDown(Keyboard.KEY_S) && sDown) {
            sDown = false;
        }
        if (getY() > 1080 || getY() < 0) {
            die();
        }
        super.update(millis);
    }
    /* if next is false, go to previous party member
     * if next is true, go to next party member
     */

    public void changePartyCharacter(boolean next) {
        String sprite = "";
        int partySize = partySprites.size();
        if (next) {
            if (currentPartnerIndex == partySize - 1) {
                currentPartnerIndex = 0;
            } else {
                currentPartnerIndex++;
            }
        } else {
            if (currentPartnerIndex == 0) {
                currentPartnerIndex = partySize - 1;
            } else {
                currentPartnerIndex--;
            }
        }
        partner.setCurrent(partySprites.get(currentPartnerIndex));
    }

    @Override
    public void die() {
        super.die();
        Display.destroy();
        JOptionPane.showMessageDialog(null, "You died.");
        System.exit(0);
    }
    
    public void win() {
        Display.destroy();
        JOptionPane.showMessageDialog(null, "You win!");
        System.exit(0);
    }

    public Level getCurrentStage() {
        return currentStage;
    }

    @Override
    void setSEngine(SpriteEngine sengine) {
        super.setSEngine(sengine);
        this.currentStage = (Level) sengine;
    }

    @Override
    public void keyEvent(int key, boolean down) {
        // This is mostly handled in update()
    }

    @Override
    public void mouseDown(int x, int y, boolean rightButton) {
        if (!rightButton) {
            float adjx = x - getX() + getWidth()/2;
            float adjy = y - getY() - getHeight()/2;
            float distance = (float) Math.hypot(adjy, adjx);
            float angle = (float) Math.atan2(adjy, adjx);
            getEquipment().click(distance, angle);
        }
    }

    @Override
    public void equip(Equipment equip) {
        Equipment primary = getEquipment();
        if (primary != null && primary instanceof Sprite) {
            ((Sprite) primary).rmSelf();
        }
        super.equip(equip);
    }
}
